package model

import (
	"database/sql"
	"fmt"
	"strings"

	"github.com/tal-tech/go-zero/core/stores/cache"
	"github.com/tal-tech/go-zero/core/stores/sqlc"
	"github.com/tal-tech/go-zero/core/stores/sqlx"
	"github.com/tal-tech/go-zero/core/stringx"
	"github.com/tal-tech/go-zero/tools/goctl/model/sql/builderx"
)

var (
	tbAlarmFieldNames          = builderx.RawFieldNames(&TbAlarm{})
	tbAlarmRows                = strings.Join(tbAlarmFieldNames, ",")
	tbAlarmRowsExpectAutoSet   = strings.Join(stringx.Remove(tbAlarmFieldNames, "`id`", "`create_time`", "`update_time`"), ",")
	tbAlarmRowsWithPlaceHolder = strings.Join(stringx.Remove(tbAlarmFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?"

	cacheTbAlarmIdPrefix = "cache::tbAlarm:id:"
)

type (
	TbAlarmModel interface {
		Insert(data TbAlarm) (sql.Result, error)
		FindOne(id int64) (*TbAlarm, error)
		Update(data TbAlarm) error
		Delete(id int64) error
	}

	defaultTbAlarmModel struct {
		sqlc.CachedConn
		table string
	}

	TbAlarm struct {
		Id       int64          `db:"id"`
		Sn       sql.NullString `db:"sn"`       // 设备唯一号
		Posno    sql.NullString `db:"posno"`    // 终端编号
		City     sql.NullString `db:"city"`     // 城市代码
		Tyid     sql.NullString `db:"tyid"`     // 设备类型
		Sver     sql.NullString `db:"sver"`     // 软件版本号
		Carno    sql.NullString `db:"carno"`    // 车辆编号
		Unum1    sql.NullInt64  `db:"unum1"`    // 未传记录数--公交
		Unum2    sql.NullInt64  `db:"unum2"`    // 未传记录数--三方
		Datetime sql.NullString `db:"datetime"` // 当前时间
		Amount   sql.NullInt64  `db:"amount"`   // 当班总额
		Count    sql.NullInt64  `db:"count"`    // 当班人数
		Line     sql.NullInt64  `db:"line"`     // 线路编号
		Stime    sql.NullString `db:"stime"`    // 开机时间
		Ctime    sql.NullString `db:"ctime"`    // 关机时间
		Pver     sql.NullInt64  `db:"pver"`     // 票价版本
		Bver     sql.NullInt64  `db:"bver"`     // 黑名单版本
		Empid    sql.NullString `db:"empid"`    // 司机编号
		Jd       sql.NullString `db:"jd"`       // 经度
		Wd       sql.NullString `db:"wd"`       // 维度
		Rvs1     sql.NullString `db:"rvs1"`     // 保留
		Rvs2     sql.NullString `db:"rvs2"`     // 保留备用
		Tenant   sql.NullInt64  `db:"tenant"`   // 租户号
		Alarm    sql.NullInt64  `db:"alarm"`    // 设备报警码
		Info     sql.NullString `db:"info"`     // 报警信息
	}
)

func NewTbAlarmModel(conn sqlx.SqlConn, c cache.CacheConf) TbAlarmModel {
	return &defaultTbAlarmModel{
		CachedConn: sqlc.NewConn(conn, c),
		table:      "`tb_alarm`",
	}
}

func (m *defaultTbAlarmModel) Insert(data TbAlarm) (sql.Result, error) {
	query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, tbAlarmRowsExpectAutoSet)
	ret, err := m.ExecNoCache(query, data.Sn, data.Posno, data.City, data.Tyid, data.Sver, data.Carno, data.Unum1, data.Unum2, data.Datetime, data.Amount, data.Count, data.Line, data.Stime, data.Ctime, data.Pver, data.Bver, data.Empid, data.Jd, data.Wd, data.Rvs1, data.Rvs2, data.Tenant, data.Alarm, data.Info)

	return ret, err
}

func (m *defaultTbAlarmModel) FindOne(id int64) (*TbAlarm, error) {
	tbAlarmIdKey := fmt.Sprintf("%s%v", cacheTbAlarmIdPrefix, id)
	var resp TbAlarm
	err := m.QueryRow(&resp, tbAlarmIdKey, func(conn sqlx.SqlConn, v interface{}) error {
		query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", tbAlarmRows, m.table)
		return conn.QueryRow(v, query, id)
	})
	switch err {
	case nil:
		return &resp, nil
	case sqlc.ErrNotFound:
		return nil, ErrNotFound
	default:
		return nil, err
	}
}

func (m *defaultTbAlarmModel) Update(data TbAlarm) error {
	tbAlarmIdKey := fmt.Sprintf("%s%v", cacheTbAlarmIdPrefix, data.Id)
	_, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
		query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, tbAlarmRowsWithPlaceHolder)
		return conn.Exec(query, data.Sn, data.Posno, data.City, data.Tyid, data.Sver, data.Carno, data.Unum1, data.Unum2, data.Datetime, data.Amount, data.Count, data.Line, data.Stime, data.Ctime, data.Pver, data.Bver, data.Empid, data.Jd, data.Wd, data.Rvs1, data.Rvs2, data.Tenant, data.Alarm, data.Info, data.Id)
	}, tbAlarmIdKey)
	return err
}

func (m *defaultTbAlarmModel) Delete(id int64) error {

	tbAlarmIdKey := fmt.Sprintf("%s%v", cacheTbAlarmIdPrefix, id)
	_, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
		query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
		return conn.Exec(query, id)
	}, tbAlarmIdKey)
	return err
}

func (m *defaultTbAlarmModel) formatPrimary(primary interface{}) string {
	return fmt.Sprintf("%s%v", cacheTbAlarmIdPrefix, primary)
}

func (m *defaultTbAlarmModel) queryPrimary(conn sqlx.SqlConn, v, primary interface{}) error {
	query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", tbAlarmRows, m.table)
	return conn.QueryRow(v, query, primary)
}
